/*Abgabe1aufg1*/
import de.medieninf.ads.*;;

/**Mainklasse und Programm zum manipulieren
 * von Graustufenbildern im pgm-Format.
 * Ausser der Mainmethode gibt es 4 weitere
 * Methoden zum manipulieren der Bilder.
 * 
 * Methoden:  heller, gamma, spreizen, binarisieren und errorMsg
 * 
 * @authoren Anna Maciejewska, Gerd Ohlweiler, Björn Klemm
 *
 */
public class Aufgabe1bk {
	
	/**
	 * 
	 * @param args 4 Übergabeparameter immer in folgender Reihenfolge
	 * Methode,Wert,Einlesebild,Ausgabebild
	 */
	public static void main(String[] args){

		String method = "";
		
		if(args.length != 4)
			errorMsg();
		else{
			method = args[0];
		}
		if(method.equals("gamma" )
				&& args[2].endsWith(".pgm")
				&& args[3].endsWith(".pgm")){
			gamma(Double.parseDouble(args[1]),ADSTool.readPGM(args[2]),args[3]);
		}
		else if(method.equals("heller") 
				&& args[2].endsWith(".pgm") 
				&& args[3].endsWith(".pgm")){
			heller(Integer.parseInt(args[1]),ADSTool.readPGM(args[2]),args[3]);
		}
		else if(method.equals("spreizen")
				&& args[2].endsWith(".pgm") 
				&& args[3].endsWith(".pgm")){
			spreizen(Integer.parseInt(args[1]),ADSTool.readPGM(args[2]),args[3]);
		}
		else if(method.equals("binarisieren")
				&& args[2].endsWith(".pgm") 
				&& args[3].endsWith(".pgm")){
			binarisieren(Integer.parseInt(args[1]),ADSTool.readPGM(args[2]),args[3]);
		}
		else
			errorMsg();	
	}
	/**
	 * 
	 * @param value Gamma
	 * @param pgmIn eingelesenes Bild im pgm-Format
	 * @param filename Ausgabedatei im pgm-Format
	 */
	private static void gamma(double value,int[]pgmIn,String filename){
		if(value >= 0.0 && value <= 10.0){
			for(int i=3; i < pgmIn.length; i++){
				pgmIn[i] = (int) (pgmIn[i] * Math.pow((double) pgmIn[i]/(double) pgmIn[2], value));
			}
			ADSTool.savePGM(filename, pgmIn);
		} else 
			errorMsg();
	}
	/**
	 * 
	 * @param value Prozent
	 * @param pgmIn eingelesenes Bild im pgm-Format
	 * @param filename Ausgabedatei im pgm-Format
	 */
	private static void heller(int value,int[]pgmIn,String filename){
		if(value >= -100 && value <= 100){
			for(int i=3; i < pgmIn.length; i++){
				pgmIn[i] += value*pgmIn[2]/100;
				if(pgmIn[i] > 255){
					pgmIn[i] = 255;
				}
			}
			ADSTool.savePGM(filename, pgmIn);
		} else
			errorMsg();
	}
	/**
	 * 
	 * @param value Pixelverteilungswert
	 * @param pgmIn eingelesenes Bild im pgm-Format
	 * @param filename Ausgabedatei im pgm-Format
	 */
	private static void spreizen(int value,int[]pgmIn,String filename){
		int top = pgmIn[2];
		int bottom = 0;
		int newBottom = getSmallestPixel(pgmIn); //a
		int newTop = getLargestPixel(pgmIn); //b
		
		for (int i = 3; i < pgmIn.length; i++) {
			
			if(value == 100) {
				pgmIn[i] = (int) (top*(((double)pgmIn[i]-bottom)/((double)top-bottom)));
			} else if(value < 100) {
				double calBottom = (newBottom*((double)((100-value))/100));
				bottom = (int)calBottom;
				double calTop = newTop+(top-newTop)*(double)(value)/100;
				top = (int)calTop;
				pgmIn[i] = (int) (top*(((double)pgmIn[i]-bottom)/((double)top-bottom)));		
			}
		}
		ADSTool.savePGM(filename, pgmIn);
	}
	/**
	 * 
	 * @param value s
	 * @param pgmIn eingelesenes Bild im pgm-Format
	 * @param filename Ausgabedatei im pgm-Format
	 */
	private static void binarisieren(int value,int[]pgmIn,String filename){
		if(value >= 0 && value <= 100){		
			for(int i=3; i < pgmIn.length; i++){
				pgmIn[i] = ((pgmIn[i]-value)+1)/2;
				if(pgmIn[i] >= value)
					pgmIn[i] = pgmIn[2];
				else
					pgmIn[i] = 0;
			}
			ADSTool.savePGM(filename, pgmIn);
		} else
			errorMsg();
	}
	/**
	 * Methode zum Anzeigen: Wie benutze ich das Programm?
	 * Nach der Hilfeanzeige wird das Programm beendet.
	 */
	public static void errorMsg(){
		System.out.println("----------------------------------------------------------------------------------------------------------------------------------");
		System.out.println("|                                                                                                                         	     |");
		System.out.println("|	Sie muessen 4 Parameter angeben! methode(Param1) wert(Param2) einlesebild.pgm(Param3) ausgabebild.pgm(Param4)           	 |");
		System.out.println("|	Bsp. java -jar aufg1.jar gamma 1.4 a.pgm out.pgm                                                                             |");
		System.out.println("|	Bitte Kleinschreibung und korrekte Reihenfolge beachten!                                                                     |");
		System.out.println("|	Bei dem Bilddateiformat muss es sich um das PGM-Format handeln!                                                              |");
		System.out.println("|	Methodenauswahl (Wertebereich) > gamma (0.0 - 10.0), heller (-100 - +100), spreizen (0 - 100), binarisieren (0 - 100)        |");
		System.out.println("|                                                                                                                            	 |");
		System.out.println("----------------------------------------------------------------------------------------------------------------------------------");
		System.exit(-1);
	}
	/**
	 * Returns the smallest pixel in the source image
	 * @param sourceImage
	 * @return
	 */
	public static int getSmallestPixel(int[]sourceImage) {
		
		int smallestValue = sourceImage[3];
		if(sourceImage[3] == 0)
			return 0;
		else {
			for(int i=3;i<sourceImage.length;i++) {
				if(sourceImage[i]<smallestValue)
					smallestValue = sourceImage[i];
			}
		}
		return smallestValue;
		
	}
	
	/**
	 * Returns the largest pixel in the source image
	 * @param sourceImage
	 * @return
	 */
	public static int getLargestPixel(int[]sourceImage) {
		
		int largestValue = sourceImage[3];
		if(sourceImage[3] == sourceImage[2])
			return sourceImage[2];
		else {
			for(int i=3;i<sourceImage.length;i++) {
				if(sourceImage[i]>largestValue)
					largestValue = sourceImage[i];
			}
		}
		return largestValue;
	}
}
